package com.myplans.client.presenter;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.myplans.client.HistoryTokens;
import com.myplans.client.Presenter;
import com.myplans.client.UserUtil;
import com.myplans.client.event.ViewPlanEvent;
import com.myplans.client.service.PlanServiceAsync;
import com.myplans.client.service.UserServiceAsync;
import com.myplans.client.util.CookieManager;
import com.myplans.client.view.BaseView;
import com.myplans.client.view.custom.PlanPanel;
import com.myplans.shared.Category;
import com.myplans.shared.Plan;
import com.myplans.shared.User;


public class HomePresenter implements Presenter {

	public interface Display {

		public Widget asWidget();
		
		public FlowPanel getPlansPanel();
		
		public FlowPanel getCategoriesPanel();
		
		public FlowPanel getRecommendedPlansPanel();

	}

	private HandlerManager eventBus;
	private Display display;
	private UserServiceAsync userServiceAsync;
	private PlanServiceAsync planService;
	private List<Hyperlink> categoriesHyperlinks = new ArrayList<Hyperlink>();

	public HomePresenter(HandlerManager eventBus, Display display) {
		this.eventBus = eventBus;
		this.display = display;
		this.bind();
	}
	
	ArrayList<Plan> recommendedPlans;

	public void go(HasWidgets container) {
		((BaseView)container).getCentralPanel().clear();
		((BaseView)container).getCentralPanel().add(display.asWidget());
		if (CookieManager.getSessionId() != null) {
			userServiceAsync.signInUser(CookieManager.getUsername(), CookieManager.getPassword(), 
					new AsyncCallback<User>() {
				
						@Override
						public void onSuccess(User result) {
							UserUtil.user = result;
							userServiceAsync.getRecommendedPlansForUser(result, new AsyncCallback<ArrayList<Plan>>() {
								
								@Override
								public void onSuccess(ArrayList<Plan> result) {
									if (result.size() > 0) {
										Label label = new Label("Recommended for you");
										label.setStyleName("userName");
										display.getRecommendedPlansPanel().add(label);
										for (Plan plan : result) {
											final PlanPanel panel = new PlanPanel(plan, false);
											display.getRecommendedPlansPanel().add(panel);
											panel.getTitleLabel().addClickHandler(new ClickHandler() {
												
												@Override
												public void onClick(ClickEvent event) {
													eventBus.fireEvent(new ViewPlanEvent(panel.getPlan()));
												}
											});
											panel.getAttendButton().addClickHandler(new ClickHandler() {
												
												@Override
												public void onClick(ClickEvent event) {
													if (panel.isAttending() == true) {
														userServiceAsync.deletePlanForUser(panel.getPlan(), UserUtil.user
																, new AsyncCallback<User>() {
																
																	@Override
																	public void onSuccess(User result) {
																		panel.setAttending(false);
																	}
																
																	@Override
																	public void onFailure(Throwable caught) {
																		Window.alert("Could not de-attend this plan");
																	}
														});
													} else {
														userServiceAsync.createPlanForUser(panel.getPlan(), UserUtil.user
																, new AsyncCallback<User>() {
																
																	@Override
																	public void onSuccess(User result) {
																		panel.setAttending(true);
																	}
																
																	@Override
																	public void onFailure(Throwable caught) {
																		Window.alert("Could not attend this plan");
																	}
														});
													}
												}
											});
										}
									}									
								}
								
								@Override
								public void onFailure(Throwable caught) {
									// TODO Auto-generated method stub
									
								}
							});
							getPlans(null);
						}

						@Override
						public void onFailure(Throwable caught) {
							// TODO Auto-generated method stub

						}
					});
			((BaseView)container).replaceLinks(true);
			
		} else {
			((BaseView)container).replaceLinks(false);
			getPlans(null);
		}
		planService.getCategories(new AsyncCallback<List<Category>>() {
			
			@SuppressWarnings("deprecation")
			@Override
			public void onSuccess(List<Category> result) {
				final Hyperlink hyperlink = new Hyperlink("All", HistoryTokens.HOME.getId());
				hyperlink.setStyleName("hyperlinkMenu");
				hyperlink.addStyleName("hyperlinkMenu-selected");
				hyperlink.addClickHandler(new ClickHandler() {
					
					@Override
					public void onClick(ClickEvent event) {
						for (Hyperlink link : categoriesHyperlinks) {
							link.removeStyleName("hyperlinkMenu-selected");
						}
						hyperlink.addStyleName("hyperlinkMenu-selected");
						getPlans(null);
					}
				});
				categoriesHyperlinks.add(hyperlink);
				display.getCategoriesPanel().add(hyperlink);
				List<Category> categories = result;
				for (Category category : categories) {
					final Hyperlink hyperlink2 = new Hyperlink(category.getName(), HistoryTokens.HOME.getId());
					hyperlink2.setStyleName("hyperlinkMenu");
					hyperlink2.addClickHandler(new ClickHandler() {
						
						@Override
						public void onClick(ClickEvent event) {
							for (Hyperlink link : categoriesHyperlinks) {
								link.removeStyleName("hyperlinkMenu-selected");
							}
							hyperlink2.addStyleName("hyperlinkMenu-selected");
							getPlans(hyperlink2.getText());
						}
					});
					categoriesHyperlinks.add(hyperlink2);
					display.getCategoriesPanel().add(hyperlink2);
				}
			}
			
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Could not get categories");
			}
		});
	}
	
	public void getPlans(final String categoryName) {
		display.getPlansPanel().clear();
		userServiceAsync.getPlansForUser(UserUtil.user, new AsyncCallback<ArrayList<Plan>>() {
			
			@Override
			public void onSuccess(ArrayList<Plan> result) {
				final ArrayList<Plan> userPlans = result;
				planService.getPlans(categoryName, null, new AsyncCallback<List<Plan>>() {
					
					@Override
					public void onSuccess(List<Plan> result) {
						for (Plan plan : result) {
							final PlanPanel panel = new PlanPanel(plan, userPlans.contains(plan));
							display.getPlansPanel().add(panel);
							panel.getTitleLabel().addClickHandler(new ClickHandler() {
								
								@Override
								public void onClick(ClickEvent event) {
									eventBus.fireEvent(new ViewPlanEvent(panel.getPlan()));
								}
							});
							panel.getAttendButton().addClickHandler(new ClickHandler() {
								
								@Override
								public void onClick(ClickEvent event) {
									if (panel.isAttending() == true) {
										userServiceAsync.deletePlanForUser(panel.getPlan(), UserUtil.user
												, new AsyncCallback<User>() {
												
													@Override
													public void onSuccess(User result) {
														panel.setAttending(false);
													}
												
													@Override
													public void onFailure(Throwable caught) {
														Window.alert("Could not de-attend this plan");
													}
										});
									} else {
										userServiceAsync.createPlanForUser(panel.getPlan(), UserUtil.user
												, new AsyncCallback<User>() {
												
													@Override
													public void onSuccess(User result) {
														panel.setAttending(true);
													}
												
													@Override
													public void onFailure(Throwable caught) {
														Window.alert("Could not attend this plan");
													}
										});
									}
								}
							});
						}
			}
			
			@Override
			public void onFailure(Throwable caught) {
				Window.alert("Could not get plans for user222");
			}
		});
		
			}

			@Override
			public void onFailure(Throwable caught) {
				// TODO Auto-generated method stub
				
			}
		});
	}
	
	private void bind() {
	}

	public void setUsersService(UserServiceAsync userServiceAsync) {
		this.userServiceAsync = userServiceAsync;
	}

	public void setPlanService(PlanServiceAsync planServiceAsync) {
		this.planService = planServiceAsync;
	}

}
